package com.viknix.threadpool.manager.client.spi;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: Dongqi
 * @Date: 2021/10/26 16:10
 * @Version 1.0
 * @Description: SPI ServiceLoader
 */
public class TpServiceLoader {

    /**
     * 所有通过Spi接入的阻塞队列对象会被缓存到当前集合中
     * key：spi接口class对象
     * value：spi实现类集合
     */
    private static final Map<Class<?>, Collection<Object>> LOAD_MAP = new ConcurrentHashMap();

    static {
        /**
         * 通过spi机制加载所有的实现类，并且注册到 LOAD_MAP 中
         */
        register(CustomBlockingQueue.class);
        register(CustomRejectedHandler.class);
    }

    /**
     * 通过spi机制加载所有的实现类，并且注册到 LOAD_MAP 中
     * @param serviceInterface 需要 ServiceLoader 加载的接口class对象
     */
    public static void register(final Class serviceInterface) {
        if (!LOAD_MAP.containsKey(serviceInterface)) {
            // 将结果所有的实现类放到map中
            LOAD_MAP.put(serviceInterface, load(serviceInterface));
        }
    }

    /**
     * 通过spi机制加载 serviceInterface 的实现类集合
     * @param serviceInterface spi接口class对象
     * @param <T> spi接口类型
     * @return serviceInterface 接口所有的实现类
     */
    private static <T> Collection<T> load(final Class<T> serviceInterface) {
        Collection<T> result = new LinkedList<>();
        // SPI 加载 serviceInterface 接口的所有实现类，并且放到 result 集合中
        for (T each : ServiceLoader.load(serviceInterface)) {
            result.add(each);
        }
        return result;
    }

    /**
     * 返回 LOAD_MAP 中，接口所有的实现类集合
     * @param serviceInterface spi接口class对象
     * @param <T> spi接口类型
     * @return LOAD_MAP 中，接口所有的实现类集合
     */
    public static <T> Collection<T> getSingletonServiceInstances(final Class<T> serviceInterface) {
        return (Collection<T>) LOAD_MAP.getOrDefault(serviceInterface, Collections.emptyList());
    }
}
